#include "PlayerTank.h"
#include "Terrain.h"
#include <cmath>

PlayerTank::PlayerTank()
    : m_pBodyMesh(NULL)
    , m_pTurretMesh(NULL)
    , m_pBarrelMesh(NULL)
    , m_pDirectionMesh(NULL)
    , m_pTexture(NULL)
    , m_health(100.0f)
    , m_maxHealth(100.0f)
    , m_shootCooldown(1.0f)
    , m_currentCooldown(0.0f)
    , m_pTerrain(NULL)
    , m_pObstacles(NULL)
    , m_speed(25.0f)
    , m_turnSpeed(D3DX_PI / 2.0f)  // 90 degrees/sec
    , m_turretYaw(0.0f)
    , m_turretTurnSpeed(D3DX_PI)   // 180 degrees/sec
    , m_hWnd(NULL)
{
}

PlayerTank::~PlayerTank()
{
    Cleanup();
}

bool PlayerTank::Initialize(LPDIRECT3DDEVICE9 device, const D3DXVECTOR3& startPos)
{
    SetPosition(startPos);
    m_hWnd = FindWindow(L"DX9TankGame", NULL);

    // Create tank body (main hull) - 10x5x8 box
    HRESULT hr = D3DXCreateBox(device, 10.0f, 5.0f, 8.0f, &m_pBodyMesh, NULL);
    if (FAILED(hr))
        return false;

    // Create turret (smaller box on top) - 6x3x6 box
    hr = D3DXCreateBox(device, 6.0f, 3.0f, 6.0f, &m_pTurretMesh, NULL);
    if (FAILED(hr))
        return false;

    // Create gun barrel (cylinder) - radius 1.5, length 8
    hr = D3DXCreateCylinder(device, 1.5f, 1.5f, 8.0f, 12, 1, &m_pBarrelMesh, NULL);
    if (FAILED(hr))
        return false;

    // Create direction indicator (flat wedge) - base radius 3.0, height 1.5
    hr = D3DXCreateCylinder(device, 3.0f, 0.0f, 1.5f, 12, 1, &m_pDirectionMesh, NULL);
    if (FAILED(hr))
        return false;

    // Set bounding box (local space, for body only)
    m_boundingBox = AABB(
        D3DXVECTOR3(-5.0f, -2.5f, -4.0f),
        D3DXVECTOR3(5.0f, 2.5f, 4.0f)
    );

    // Create texture (green color for player)
    hr = D3DXCreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8,
        D3DPOOL_MANAGED, &m_pTexture);
    if (SUCCEEDED(hr))
    {
        D3DLOCKED_RECT rect;
        m_pTexture->LockRect(0, &rect, NULL, 0);
        DWORD* pTexels = (DWORD*)rect.pBits;

        // Green camouflage pattern
        for (int i = 0; i < 64 * 64; i++)
        {
            int x = i % 64;
            int y = i / 64;
            if ((x / 8 + y / 8) % 2 == 0)
                pTexels[i] = D3DCOLOR_ARGB(255, 60, 120, 60);
            else
                pTexels[i] = D3DCOLOR_ARGB(255, 80, 140, 80);
        }
        m_pTexture->UnlockRect(0);
    }

    return true;
}

void PlayerTank::Update(float deltaTime)
{
    if (IsDead())
        return;

    // Update cooldown
    m_currentCooldown -= deltaTime;
    if (m_currentCooldown < 0.0f)
        m_currentCooldown = 0.0f;

    // Process input
    ProcessInput(deltaTime);
}

void PlayerTank::ProcessInput(float deltaTime)
{
    // Movement: W/S - forward/backward
    D3DXVECTOR3 forward(sin(m_rotation.y), 0.0f, cos(m_rotation.y));
    D3DXVECTOR3 velocity(0, 0, 0);

    if (IsKeyDown('W'))
    {
        velocity = forward * m_speed * deltaTime;
    }
    if (IsKeyDown('S'))
    {
        velocity = forward * -m_speed * deltaTime;
    }

    // Rotation: A/D - turn left/right
    if (IsKeyDown('A'))
    {
        m_rotation.y += m_turnSpeed * deltaTime;
    }
    if (IsKeyDown('D'))
    {
        m_rotation.y -= m_turnSpeed * deltaTime;
    }

    // Apply movement
    if (D3DXVec3Length(&velocity) > 0.01f)
    {
        D3DXVECTOR3 newPos = m_position + velocity;

        // Update Y coordinate based on terrain
        if (m_pTerrain)
        {
            newPos.y = m_pTerrain->GetHeight(newPos.x, newPos.z) + 2.5f;  // 2.5f is half of body height
        }

        // Check map boundaries
        if (newPos.x >= 0.0f && newPos.x <= 1000.0f &&
            newPos.z >= 0.0f && newPos.z <= 1000.0f)
        {
            // Check collision
            if (!CheckCollisionAtPosition(newPos))
            {
                SetPosition(newPos);
            }
        }
    }

    // Turret rotation: Q/E keys
    if (IsKeyDown('Q'))
    {
        m_turretYaw += m_turretTurnSpeed * deltaTime;
    }
    if (IsKeyDown('E'))
    {
        m_turretYaw -= m_turretTurnSpeed * deltaTime;
    }

    // Shooting: Space or Left Mouse Button
    if (IsKeyDown(VK_SPACE) || IsKeyDown(VK_LBUTTON))
    {
        if (m_currentCooldown <= 0.0f)
        {
            Shoot();
            m_currentCooldown = m_shootCooldown;
        }
    }
}

void PlayerTank::ProcessMouseInput(int deltaX, int deltaY, float deltaTime)
{
    // Mouse control for turret (optional, can be used alongside Q/E)
    float sensitivity = 0.002f;
    m_turretYaw -= deltaX * sensitivity;
}

bool PlayerTank::IsKeyDown(int vKey)
{
    return (GetAsyncKeyState(vKey) & 0x8000) != 0;
}

bool PlayerTank::CheckCollisionAtPosition(const D3DXVECTOR3& newPos)
{
    if (!m_pObstacles)
        return false;

    // Create temporary object to test collision
    GameObject tempObj;
    tempObj.SetPosition(newPos);
    tempObj.SetBoundingBox(m_boundingBox);

    for (size_t i = 0; i < m_pObstacles->size(); i++)
    {
        if (tempObj.CheckCollision(*(*m_pObstacles)[i]))
        {
            return true;  // Collision detected
        }
    }

    return false;
}

void PlayerTank::TakeDamage(float damage)
{
    m_health -= damage;
    if (m_health < 0.0f)
        m_health = 0.0f;
}

void PlayerTank::Shoot()
{
    // Shooting logic will be handled by main.cpp creating Projectile
    // This function is called to signal a shot was fired
}

D3DXVECTOR3 PlayerTank::GetTurretDirection() const
{
    float totalYaw = m_rotation.y + m_turretYaw;
    return D3DXVECTOR3(sin(totalYaw), 0.0f, cos(totalYaw));
}

D3DXVECTOR3 PlayerTank::GetGunDirection() const
{
    float totalYaw = m_rotation.y + m_turretYaw;

    // Gun direction (horizontal only, no pitch)
    D3DXVECTOR3 direction;
    direction.x = sin(totalYaw);
    direction.y = 0.0f;
    direction.z = cos(totalYaw);

    D3DXVec3Normalize(&direction, &direction);
    return direction;
}

D3DXVECTOR3 PlayerTank::GetGunPosition() const
{
    // Gun position is at turret top + barrel offset
    float totalYaw = m_rotation.y + m_turretYaw;

    // Turret center (on top of body)
    D3DXVECTOR3 turretPos = m_position + D3DXVECTOR3(0.0f, 4.0f, 0.0f);

    // Barrel extends forward from turret
    D3DXVECTOR3 barrelOffset(sin(totalYaw) * 4.0f, 0.0f, cos(totalYaw) * 4.0f);

    return turretPos + barrelOffset;
}

void PlayerTank::Render(LPDIRECT3DDEVICE9 device)
{
    if (!device || IsDead())
        return;

    // Set material
    D3DMATERIAL9 material = {};
    material.Diffuse.r = material.Ambient.r = 0.6f;
    material.Diffuse.g = material.Ambient.g = 0.8f;
    material.Diffuse.b = material.Ambient.b = 0.6f;
    material.Diffuse.a = material.Ambient.a = 1.0f;
    device->SetMaterial(&material);

    // Set texture
    if (m_pTexture)
        device->SetTexture(0, m_pTexture);

    // Render body
    if (m_pBodyMesh)
    {
        D3DXMATRIX matWorld, matScale, matRot, matTrans;
        D3DXMatrixScaling(&matScale, 1.0f, 1.0f, 1.0f);
        D3DXMatrixRotationY(&matRot, m_rotation.y);
        D3DXMatrixTranslation(&matTrans, m_position.x, m_position.y, m_position.z);
        matWorld = matScale * matRot * matTrans;
        device->SetTransform(D3DTS_WORLD, &matWorld);
        m_pBodyMesh->DrawSubset(0);
    }

    // Render turret (on top of body, rotates independently)
    if (m_pTurretMesh)
    {
        D3DXMATRIX matWorld, matScale, matRotBody, matRotTurret, matTrans, matTransBody;
        D3DXMatrixScaling(&matScale, 1.0f, 1.0f, 1.0f);
        D3DXMatrixRotationY(&matRotBody, m_rotation.y);
        D3DXMatrixRotationY(&matRotTurret, m_turretYaw);

        // Turret position offset (top of body)
        D3DXMatrixTranslation(&matTransBody, 0.0f, 4.0f, 0.0f);  // 2.5 (half body) + 1.5 (half turret)
        D3DXMatrixTranslation(&matTrans, m_position.x, m_position.y, m_position.z);

        matWorld = matScale * matRotTurret * matTransBody * matRotBody * matTrans;
        device->SetTransform(D3DTS_WORLD, &matWorld);
        m_pTurretMesh->DrawSubset(0);
    }

    // Render gun barrel (extends from turret front, horizontal)
    if (m_pBarrelMesh)
    {
        D3DXMATRIX matWorld, matRotBody, matRotTurret;
        D3DXMATRIX matTrans, matTransBarrel, matTransBody;

        // 车体和炮塔旋转
        D3DXMatrixRotationY(&matRotBody, m_rotation.y);
        D3DXMatrixRotationY(&matRotTurret, m_turretYaw);

        // 炮管位置：炮塔前方 4 单位（圆柱体默认就是竖直的，Y轴是长轴，高度8单位，所以向前偏移4）
        // 圆柱体中心在原点，底面Y=-4，顶面Y=+4，我们要让它水平放置，底部在炮塔中心
        D3DXMatrixTranslation(&matTransBarrel, 0.0f, 0.0f, 4.0f);
        // 炮塔高度偏移
        D3DXMatrixTranslation(&matTransBody, 0.0f, 4.0f, 0.0f);
        // 世界位置
        D3DXMatrixTranslation(&matTrans, m_position.x, m_position.y, m_position.z);

        // 直接平移，不旋转（测试圆柱体原始朝向）
        matWorld = matTransBarrel * matRotTurret * matTransBody * matRotBody * matTrans;
        device->SetTransform(D3DTS_WORLD, &matWorld);
        m_pBarrelMesh->DrawSubset(0);
    }

    // Render direction indicator (flat wedge on front of tank body)
    if (m_pDirectionMesh)
    {
        // 使用橙黄色材质，醒目的方向指示
        D3DMATERIAL9 dirMaterial = {};
        dirMaterial.Diffuse.r = dirMaterial.Ambient.r = 1.0f;
        dirMaterial.Diffuse.g = dirMaterial.Ambient.g = 0.8f;
        dirMaterial.Diffuse.b = dirMaterial.Ambient.b = 0.2f;
        dirMaterial.Diffuse.a = dirMaterial.Ambient.a = 1.0f;
        device->SetMaterial(&dirMaterial);

        D3DXMATRIX matWorld, matRotBody, matRotX;
        D3DXMATRIX matTrans, matTransCone;

        // 圆锥体默认底部在 Y=-0.75，尖端在 Y=+0.75（高度1.5）
        // 我们要让它水平指向前方（Z轴正方向），所以绕 X 轴旋转 90 度
        D3DXMatrixRotationX(&matRotX, -D3DX_PI / 2.0f);  // 尖端指向 +Z

        // 车体旋转
        D3DXMatrixRotationY(&matRotBody, m_rotation.y);

        // 位置：车体前端（Z=+4），高度在车体底部（Y=-2.5），稍微向前突出 0.75 单位
        D3DXMatrixTranslation(&matTransCone, 0.0f, -2.0f, 4.75f);  // 贴近车体底部前端

        // 世界位置
        D3DXMatrixTranslation(&matTrans, m_position.x, m_position.y, m_position.z);

        matWorld = matRotX * matTransCone * matRotBody * matTrans;
        device->SetTransform(D3DTS_WORLD, &matWorld);
        m_pDirectionMesh->DrawSubset(0);
    }
}

void PlayerTank::Cleanup()
{
    if (m_pTexture)
    {
        m_pTexture->Release();
        m_pTexture = NULL;
    }
    if (m_pDirectionMesh)
    {
        m_pDirectionMesh->Release();
        m_pDirectionMesh = NULL;
    }
    if (m_pBarrelMesh)
    {
        m_pBarrelMesh->Release();
        m_pBarrelMesh = NULL;
    }
    if (m_pTurretMesh)
    {
        m_pTurretMesh->Release();
        m_pTurretMesh = NULL;
    }
    if (m_pBodyMesh)
    {
        m_pBodyMesh->Release();
        m_pBodyMesh = NULL;
    }
}
